﻿using ECO.Admin.Application.Controllers.Auth.Dtos.InputModels;
using ECO.Admin.Application.Controllers.Auth.Dtos.OutputDtos;
using ECO.Admin.Core.Sugar;
using ECO.Admin.Core.EventBus.Dto;
using Furion.EventBus;
using MapsterMapper;
using System.Collections.Generic;
using System.Security.Cryptography;
using ECO.Admin.Core.Shared.Const;
using ECO.Admin.Core.Entities.System;
using ECO.Admin.Core.Entities.User;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;

namespace ECO.Admin.Application.Controllers.Auth.Services
{
    public class AuthService : IAuthService, ITransient
    {
        private readonly IEventPublisher _eventPublisher;
        private readonly Repository<SysUser> _userRepository;
        private readonly Repository<SysRole> _roleRepository;
        private readonly IMapper _mapper;

        public AuthService(Repository<SysUser> userRepository, IMapper mapper, Repository<SysRole> roleRepository, IEventPublisher eventPublisher)
        {
            _userRepository = userRepository;
            _mapper = mapper;
            _roleRepository = roleRepository;
            _eventPublisher = eventPublisher;
        }

        public async Task<LoginDto> Login(LoginInput loginInput)
        {

            var user = await _userRepository.GetFirstAsync(x => x.UserName == loginInput.Account || x.Email == loginInput.Account);
            if (user == null)
            {
                throw Oops.Bah("账户不存在,登录失败!");
            }
            if (user.IsLock)
            {
                throw Oops.Bah("账户被锁定,请稍后再试!");
            }
            var loginDto = _mapper.Map<LoginDto>(user);
    
            loginDto.AccessToken = JWTEncryption.Encrypt(new Dictionary<string, object> { { "Id", user.Id }, { "Email", user.Email }, { "UserName", user.UserName } });
            var refreshToken = JWTEncryption.GenerateRefreshToken(loginDto.AccessToken, 43200);
            App.HttpContext.SetTokensOfResponseHeaders(loginDto.AccessToken, refreshToken);
            await _eventPublisher.PublishAsync(new ChannelEventSource(EventSubscriberConst.Login, new LoginEvent()
            {
                UserId = user.Id,
                IPAddress = App.HttpContext.GetRemoteIpAddressToIPv4(),
                LoginTime = DateTime.Now
            }));
            return loginDto;


        }

        public async Task<UserDto> Register(RegisterInput registerInput)
        {
            if (await _userRepository.IsAnyAsync(x => x.Email == registerInput.Email))
            {
                throw Oops.Bah("该邮箱已经注册!");
            }
            //获取随机盐
            var salt = GetSalt(6);
            var role = await _roleRepository.GetFirstAsync(x => x.RoleName == SystemRole.User) ?? new SysRole() { RoleName = SystemRole.User };
            List<SysUser> users = new List<SysUser>
            {
                new SysUser()
                {
                    Email = registerInput.Email,
                    Salt= salt,
                    Password=MD5Encryption.Encrypt(registerInput.Password+ salt),
                    UserName = registerInput.UserName,
                    Phone= registerInput.Phone,
                }
            };
            users[0].Roles = new List<SysRole> { role };
            var user = await App.GetService<ISqlSugarClient>()
                 .InsertNav(users)
                 .Include(x => x.Roles)
                 .ExecuteReturnEntityAsync();

            return _mapper.Map<UserDto>(user);

        }
        private string GetSalt(int length)
        {
            byte[] salt = new byte[length];

            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(salt);
            }
            return BitConverter.ToString(salt).Replace("-", "");
        }

    }
}